/*
 * Copyright (c) 2019-2020, https://api.iot.10086.cn/(https://gitee.com/cmcc-iot-api/iot-card-open-application/).
 */
package cn.iot.card.open.sim.service;

import cn.iot.card.open.constants.Constants;
import cn.iot.card.open.constants.ErrorCode;
import cn.iot.card.open.constants.UrlConstants;
import cn.iot.card.open.ec.dto.ResponseDto;
import cn.iot.card.open.modular.model.ResultDTO;
import cn.iot.card.open.modular.token.TokenService;
import cn.iot.card.open.pojo.page.LayuiPageFactory;
import cn.iot.card.open.pojo.page.LayuiPageInfo;
import cn.iot.card.open.sim.warpper.BusinessHandleResultWrapper;
import cn.iot.card.open.util.ApiRequestUtil;
import cn.iot.card.open.util.CommonUtil;
import cn.iot.card.open.util.JsonUtil;
import cn.stylefeng.roses.core.util.ToolUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import java.net.URLEncoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 查询业务办理结果
 *
 * @author zhanlele
 * @date 20200324 12:36:16
 * @modify 20200324 zhanlele v1.1.2 创建
 * @since v1.1.2
 */
@Service
@Slf4j
public class BusinessHandleResultService {
    @Autowired
    private TokenService tokenService;
    @Autowired
    private ApiRequestUtil apiRequestUtil;

    /**
     * 查询业务办理结果
     *
     * @param accountId 账户ID
     * @param transId   流水号
     * @param jobId     任务流水号
     * @return 返回 layui page info
     * @throws Exception
     * @author zhanlele
     * @date 20200324 12:35:00
     * @modify 20200324 zhanlele v1.1.2 创建
     * @since v1.1.2
     */
    public LayuiPageInfo queryHandleResult(String accountId, String transId, String jobId) throws Exception {
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO resultDTO = doRequestQueryHandleResult(true, accountId, transId, URLEncoder.encode(jobId));
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!resultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(resultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = resultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token [accountId:{}] of queryHandleResult is invalid and start to get a new token.", transId, accountId);
            resultDTO = doRequestQueryHandleResult(false, accountId, transId, jobId);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!resultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(resultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = resultDTO.getMsg();
        }
        log.info("[{}] query HandleResult result string is {}.", transId, responseStr);
        ResponseDto<Map<String, Object>> responseDto = JsonUtil.parseJson(responseStr,
                new TypeReference<ResponseDto<Map<String, Object>>>(){});
        code = responseDto.getStatus();
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] query HandleResult error, error message is {}.", transId, responseDto.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }

        List<Map<String, Object>> resultList = responseDto.getResult();
        Map<String, Object> resultMap = resultList.get(0);
        List<Map<String, Object>> responseList = handleResponseResult(resultMap);

        Page<Map<String, Object>> page = LayuiPageFactory.defaultPage();
        page.setTotal(responseList.size());
        page.setRecords(responseList);
        page = new BusinessHandleResultWrapper(page).wrap();
        return LayuiPageFactory.createPageInfo(page);
    }

    /**
     * 调API，查询物联卡业务办理结果
     *
     * @param tokenValid token是否有效
     * @param accountId  账户ID
     * @param transId    流水号
     * @param jobId      物联卡批量处理的任务流水号
     * @return 返回 result dto
     * @throws Exception
     * @author zhanlele
     * @date 20200320 18:30:00
     * @modify 20200320 zhanlele v1.1.2 创建
     * @since v1.1.2
     */
    private ResultDTO doRequestQueryHandleResult(boolean tokenValid, String accountId, String transId,
                                                 String jobId) throws Exception {
        ResultDTO tokenResultDTO = tokenService.getToken(tokenValid, accountId);
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            return tokenResultDTO;
        }

        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TOKEN, tokenResultDTO.getMsg());
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        parameterMap.put(Constants.REQUEST_JOB_ID, jobId);

        String methodUrl = apiRequestUtil.buildRequestUrl(parameterMap, UrlConstants.QUERY_BUSINESS_HANDLE_RESULT);
        log.info("[{}] queryHandleResult request url is {}.", transId, methodUrl);

        tokenResultDTO.setMsg(apiRequestUtil.doGet(methodUrl));
        return tokenResultDTO;
    }

    /**
     * 处理响应数据
     *
     * @param resultMap
     * @return 返回 list
     * @author zhanlele
     * @date 20200324 11:30:48
     * @modify 20200324 zhanlele v1.1.2 创建
     * @since v1.1.2
     */
    private List<Map<String, Object>> handleResponseResult(Map<String, Object> resultMap) {
        String jobStatus = (String) resultMap.get(Constants.JOB_STATUS);
        Object resultList = resultMap.get(Constants.RESPONSE_RESULT_LIST);
        List<Map<String, Object>> list = resultList != null ? (List<Map<String, Object>>) resultList : null;
        List<Map<String, Object>> handleList = new ArrayList<>();
        if (Constants.RESPONSE_DELETED_FALSE.equals(jobStatus) || Constants.RESPONSE_DELETED_TRUE.equals(jobStatus) || ToolUtil.isEmpty(list)) {
            Map<String, Object> map = new HashMap<>();
            map.put(Constants.JOB_STATUS, jobStatus);

            handleList.add(map);
            return handleList;
        }
        for (Map<String, Object> map : list) {
            map.put(Constants.JOB_STATUS, jobStatus);
            handleList.add(map);
        }

        return handleList;
    }
}
